//============================================================================
// Nome        : mapas.cpp
// Autores     : T1G7
//                                      Felipe Galvão do Espírito Santo
//                                      Ivanilda Maísa Costa Brazão de Almeida
//                                      Paulo Jorge de Faria dos Reis
// Versão      : 1.0
// Data        : Maio de 2011
// Copyright   : Creative Commons 2.0
// Descrição   : CAL 2011 - TG1
//               Tema 12 - Transporte de pacientes de uma clínica de saúde.
//============================================================================

#include "mapas.h"


//! Implementação da classe no
//! Cosntrutor.
no::no(string linha)
{
	try
	{
		if(sscanf(linha.c_str(), "%d;%f;%f;%f;%f", &identificador, &posX, &posY, &projX, &projY) == EOF) throw(linha.c_str());	//! identificador n�;latitude;longitude;projec��o plana da longitude (X); projec��o plana da latitude (Y)
	}
	catch(char * erro)
	{
		cout << "Erro a processar os dados:" << endl;
		cout << erro << endl;
		//TODO Código para processar a entrada manual do no.
	}
}

//! Destrutor.
no::~no()
{
}

bool no::operator== (no no1)
{
	if(this->identificador == no1.identificador)
		return true;
	return false;
}

int no::getID()
{
	return this->identificador;
}

float no::latitude()
{
	return posY;
}

float no::longitude()
{
	return posX;
}

no& mapa::noPorID(int ident)
{
	for(unsigned int i = 0; pontos.size(); i++)
	{
		if(ident == pontos[i].getID())
			return pontos[i];
	}
}

//! Implementação da classe morada.
//! Construtor
morada::morada(string linha)
{
	//string sentido;
	//try
	//{
	//	if(sscanf(linha.c_str(), "%d;%s;%s", &identificador, &nome, &sentido) == EOF)
	//	{
	//			throw(linha.c_str());	//! identificador;nome;sentido
	//	}
	//	if(sentido == "False")
	//	{
	//		umSentido = false;
	//	}
	//	else
	//	{
	//		umSentido = true; 
	//	}
	//}
	//catch(char * erro)
	//{
	//	cout << "Erro a processar os dados:" << endl;
	//	cout << erro << endl;
	//	//cout << "Pretende:" << endl;
	//	//cout << "1 - ignorar este n�" << endl;
	//	//cout << "2 - introduzir os dados manualmente" << endl;
	//	//cout << "3 - Cancelar o carregamento e terminar a aplica��o" << endl;
	//	
	//	//TODO C�digo para processar a entrada manual da morada.
	//}
}

//! Destrutor
morada::~morada()
{
}

//! Implementação da classe unidade.
//! Construtor
unidade::unidade(string linha)
{
	try
	{
		if(sscanf(linha.c_str(), "%d;%d;%d", &identificador, &inicio, &fim) == EOF) throw(linha.c_str());	//! identificador da rua;identificador do n� origem;identificador do n� destino;
	}
	catch(char * erro)
	{
		cout << "Erro a processar os dados:" << endl;
		cout << erro << endl;
	}
}

//! Destrutor
unidade::~unidade()
{
}

int unidade::noInicio()
{
	return inicio;
}

int unidade::noFinal()
{
	return fim;
}


//! Implementação da classe mapa
//! Construtor.
mapa::mapa(float esquerda, float direita, float cima, float baixo, int X, int Y)
{
	horizontal = X;					//! X
	vertical = Y;					//! Y
	longitudeMin = esquerda;		//! esquerda
	longitudeMax = direita;			//! direita
	latitudeMin = baixo;			//! baixo
	latitudeMax = cima;				//! cima
}

//! Destrutor
mapa::~mapa()
{
}

//! Leitura dos ficheiros de dados e carregamentos da informação
void mapa::processaMapa(char * fNodes, char * fRuas, char * fSubruas)
{
	string linha;

	//! Tratamnto do ficheiro dos nós.
	fstream fNos(fNodes);
	while(getline(fNos, linha))
	{
		pontos.push_back(no(linha));
		grafoDoMapa.addVertex(pontos.end()->getID());
		grafoDoMapa2.addVertex(noPorID(pontos.end()->getID()));
	}
	fNos.close();
	cout << "Processados " << pontos.size() << " nós geográficos, a partir do ficheiro " << fNodes << endl;
	cout << "Existem " << grafoDoMapa.getNumVertex() << " nós no grafoDoMapa" << endl;
	cout << "Existem " << grafoDoMapa2.getNumVertex() << " nós no grafoDoMapa2" << endl;

	//! Tratamento do ficheiro das ruas.
	fstream fVias(fRuas);
	while(getline(fVias, linha))
	{
		arruamentos.push_back(morada(linha));
	}
	fVias.close();
	cout << "Processadas " << arruamentos.size() << " ruas, a partir do ficheiro " << fRuas << endl;

	//! Tratamento do ficheiro das subruas.
	fstream fPontos(fSubruas);
	while(getline(fPontos, linha))
	{
		pontosInteresse.push_back(unidade(linha));
		double lat1 = (infoNo((pontosInteresse.end())->noInicio()))->latitude();
		double lat2 = (infoNo((pontosInteresse.end())->noFinal()))->latitude();
		double long1 = (infoNo((pontosInteresse.end())->noInicio()))->longitude();
		double long2 = (infoNo((pontosInteresse.end())->noFinal()))->longitude();

		grafoDoMapa.addEdge((pontosInteresse.end())->noInicio(), (pontosInteresse.end())->noFinal(), fabs(haversine_m(lat1, long1, lat2, long2)));
		//grafoDoMapa2.addEdge(noPorID((pontosInteresse.end())->noInicio()), noPorID((pontosInteresse.end())->noFinal()), fabs(haversine_m(lat1, long1, lat2, long2)));
	}
	fPontos.close();
	cout << "Processadas " << pontosInteresse.size() << " ruas, a partir do ficheiro " << fSubruas << endl;
}


vector<no>::iterator mapa::infoNo(int id)
{
	vector<no>::iterator iter;
	for(iter = pontos.begin(); iter != pontos.end(); iter++)
	{
		if(iter->getID() == id) return iter;
	}
	return iter;
}

vector<no>::iterator mapa::primeiro()
{
	vector<no>::iterator iter;
	iter = pontos.begin();
	return iter;
}

//! Construção de uma rota.
/*!
 *  Esta função devolve um vector de pontos a visitar, esses pontos são os pontos necessários para apresentar a rota mais curta na
 *  interface de visualização de grafos. Do vector de pontos a visitar vão ser retirados os pontos visitados, dessa forma ao terminar
 *  temos os pontos (clientes) que não tivemos capacidade de visitar.
 *  Esta função não está a funcionar como pretendido, razão pela qual está maioritáriamente comentada.
 */
void mapa::planearRotas(vector<int>* rotas, vector<int>* avisitar, int lugares)
{
	for(unsigned int i = 0; i < avisitar->size(); i++)
	{
		//! Enontrar os caminhos mais curtos de um ponto da nossa rota até todos os restantes.

		cout << "Vou chamar o Dij com " << avisitar->at(i) << endl;
//		grafoDoMapa.dijkstraShortestPath(avisitar->at(i));
//		cout << "Depois do Dij " << i << endl;
//		 TODO optimização para escolher o destino mais perto dos que temos de visitar. E utilizar esse como destino e n�o o seguinte da lista.
//		unsigned int j = i + 1;	//! Juntar os pontos a visitar.
//		if(j == avisitar->size())
//		{
//			j = 0;	//! Se estivermos na última recolha, voltar à 'base'.
//		}
//		vector<int> etapa = grafoDoMapa.getPath(avisitar->at(i), avisitar->at(j));
//		for(unsigned int k = 0; k < etapa.size(); k++)
//		{
//			rotas->push_back(etapa[k]);
//		}
	}
}
